package seedpod.kb2db.protegeplugin;
/**
 * Copyright 2009 University of  Washington
 * This code is released under the GPL version 3 - with a copy of the license included
 * @author Maya Hao Li
 *
 */
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.swing.JComponent;
import javax.swing.JRootPane;

import seedpod.kb2db.ProjectTransformValidator;
import seedpod.kb2db.ProjectTransformValidator.TransformValidationException;
import seedpod.model.SeedpodModel;
import seedpod.model.SeedpodSystemFrames;
import edu.stanford.smi.protege.model.Cls;
import edu.stanford.smi.protege.model.Instance;
import edu.stanford.smi.protege.model.KnowledgeBase;
import edu.stanford.smi.protege.model.Model;
import edu.stanford.smi.protege.model.Project;
import edu.stanford.smi.protege.model.Slot;
import edu.stanford.smi.protege.ui.ProjectManager;
import edu.stanford.smi.protege.util.ComponentFactory;
import edu.stanford.smi.protege.util.ModalDialog;

public class SeedpodProjectManager
{
	private static final String RDB_PREFIX = ":RDB_";
	private static ProjectManager _projectManager = ProjectManager.getProjectManager();
	private static SeedpodProjectManager _spPM = new SeedpodProjectManager();
	private KnowledgeBase _kb;
	private SeedpodSystemFrames _seedpodSysFrames;
	public static final String RESOURCE = "src/edu/washington/biostr/sig/seedpod/kb2db/protegeplugin/resource/";
	public static final String STANDARD_PROJECT_NAME = "seedpod_standard_project";

	private SeedpodProjectManager() {}

	public static SeedpodProjectManager getSeedpodProjectManager() {
		return _spPM;
	}

	public boolean createSeedpodProjectRequest() {
		boolean success = true;

		if ( !_projectManager.createNewProjectRequest() )
			return false;

		_kb = _projectManager.getCurrentProject().getKnowledgeBase();
		createSeedpodProject( _kb );

		if ( _seedpodSysFrames.getErrors().size() > 0 )
			success = false;
		return success;
	}

	private void createSeedpodProject( KnowledgeBase kb ) {
		// SeedpodKnowledgeBase sKB = new SeedpodKnowledgeBase( kb );
		// _seedpodSysFrames = sKB.getSeedpodSystemFrames();
		_seedpodSysFrames = new SeedpodSystemFrames( kb );
		_seedpodSysFrames.createSeedpodSystemFrames();
		_seedpodSysFrames.setDefaultClsMetaCls();
		_seedpodSysFrames.setDefaultSlotMetaCls();
	}

	/*
	 * merge method private void initSeedpodSystemFrames2( KnowledgeBase kb ) {
	 * _seedpodSysFrames = new SeedpodSystemFrames2( kb ); if (
	 * _seedpodSysFrames.getErrors().size() > 0 ) {
	 * _projectManager.displayErrors( "Errors occurred during initialization of
	 * seedpod system frames", _seedpodSysFrames.getErrors() ); } }
	 */

	public void convertProjectRequest() {
		int saved = promptSaveProjectAs();

		if ( saved == ModalDialog.OPTION_OK )
			convertProject();
	}

	private int promptSaveProjectAs() {
		String msg = "Your original project will be modified.  Please save it to another project.";
		int confirmation = confirmContinueSeedpod( msg );
		switch (confirmation) {
		case ModalDialog.OPTION_OK:
			_projectManager.saveProjectAsRequest();
			break;
		case ModalDialog.OPTION_CANCEL:
			break;
		}
		return confirmation;
	}

	protected void convertProject() {
		// step 1 merge seedpod system frames
		_kb = _projectManager.getCurrentProject().getKnowledgeBase();
		createSeedpodProject( _kb );

		// step 2 convert current non-system classes to RDB_CLASS, and slots to
		// RDB_ATTRIBUTE
		_kb = _projectManager.getCurrentProject().getKnowledgeBase();
		convertClsesAndSlots( _kb );
	}

	protected void convertClsesAndSlots( KnowledgeBase kb ) {
		Cls stdClsMetaCls = kb.getCls( Model.Cls.STANDARD_CLASS );
		Cls rdbClsMetaCls = kb.getCls( SeedpodModel.RdbCls.RDB_CLASS );
		Cls sysCls = kb.getCls( Model.Cls.SYSTEM_CLASS );

		Collection<Instance> stdClses = kb.getInstances( stdClsMetaCls );
		Iterator<Instance> stdClsesIter = stdClses.iterator();
		while (stdClsesIter.hasNext()) {
			Cls cls = (Cls)stdClsesIter.next();
			if ( !cls.isSystem() && !cls.hasSuperclass( sysCls ) && cls.getName().compareTo( Model.Cls.THING ) != 0 ) {
				Cls clsMetaCls = cls.getDirectType();

				if ( _seedpodSysFrames.isSeedpodSystemMetaCls( clsMetaCls ) )
					continue;
				else if ( !clsMetaCls.equals( stdClsMetaCls ) ) {
					String mergedMetaCls = getMergeMetaClsName( clsMetaCls.getName() );

					Cls mergeCls = kb.getCls( mergedMetaCls );
					if ( mergeCls == null )
						mergeCls = createNewMergedMetaCls( mergedMetaCls, clsMetaCls, rdbClsMetaCls );
					cls.addDirectType( mergeCls );
				} else
					cls.addDirectType( rdbClsMetaCls );

				cls.removeDirectType( clsMetaCls );
				convertSlots( cls, kb );
			}
		}
	}

	private String getMergeMetaClsName( String name ) {
		return RDB_PREFIX + name;
	}

	protected void convertSlots( Cls cls, KnowledgeBase kb ) {
		Cls stdSlotMetaCls = kb.getCls( Model.Cls.STANDARD_SLOT );
		Cls rdbSlotMetaCls = kb.getCls( SeedpodModel.RdbCls.RDB_SLOT );

		Iterator<Slot> stdSlotsIter = cls.getDirectTemplateSlots().iterator();
		while (stdSlotsIter.hasNext()) {
			Slot slot = (Slot)stdSlotsIter.next();
			if ( slot.hasDirectType( stdSlotMetaCls ) ) {
				slot.addDirectType( rdbSlotMetaCls );
				slot.removeDirectType( stdSlotMetaCls );
			}
		}
	}

	private Cls createNewMergedMetaCls( String newClsName, Cls customClsMetaCls, Cls rdbClsMetaCls ) {
		Collection<Cls> parents = new ArrayList<Cls>();
		parents.add( rdbClsMetaCls );
		parents.add( customClsMetaCls );
		Cls mergeClsMetaCls = _kb.getCls( Model.Cls.STANDARD_CLASS );
		Cls mergeCls = _kb.createCls( newClsName, parents, mergeClsMetaCls );
		return mergeCls;
	}

	private static int confirmContinueSeedpod( String prompt ) {
		JRootPane rootPane = _projectManager.getCurrentProjectView().getRootPane();
		JComponent c = ComponentFactory.createLabel( prompt );
		int result = ModalDialog.showDialog( rootPane, c, "Save?", ModalDialog.MODE_OK_CANCEL );
		return result;
	}

	public static void validateProjectRequest()  {
		KnowledgeBase kb = _projectManager.getCurrentProject().getKnowledgeBase();
		ProjectTransformValidator validator = new ProjectTransformValidator( kb );
		try {
			if ( validator.validateKB() ) {
				showValidateMsg();
			} else {
				_projectManager.displayErrors( "Project Not Validated", validator.getErrors() );
			}
		}
		catch ( TransformValidationException e0 ) {
			e0.printStackTrace();
		}
		
	}

	private static void showValidateMsg() {
		JRootPane rootPane = _projectManager.getCurrentProjectView().getRootPane();
		JComponent c = ComponentFactory.createLabel( "Project validated." );
		ModalDialog.showDialog( rootPane, c, "", ModalDialog.MODE_CLOSE );
	}

	public void exportToSQLRequest() {
		Protege2SQLExportPlugin plugin = new Protege2SQLExportPlugin();
		Project project = _projectManager.getCurrentProject();
		plugin.handleExportRequest( project );
	}

}
